package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"github.com/fatih/structs"
	"gorm.io/gorm/clause"
)

type MenuSrv struct{}

func (r *MenuSrv) MenuTree() response.Resp {
	err, menusMap := r.menusMap()
	menuList := menusMap[0]

	for i := 0; i < len(menuList); i++ {
		err = r.appendChildren(&menuList[i], menusMap)
	}
	if err != nil {
		return response.ErrQuery.SetMsg("格式化菜单失败")
	}

	return response.OK.WithData(menuList)
}

func (r *MenuSrv) menusMap() (error, map[uint][]model.MenuTree) {
	var menus []model.MenuTree
	err := global.Gorm.Model(&model.Menu{}).Order("sort asc").Find(&menus).Error
	if err != nil {
		return err, map[uint][]model.MenuTree{}
	}
	menusMap := make(map[uint][]model.MenuTree)
	for _, v := range menus {
		menusMap[v.Pid] = append(menusMap[v.Pid], v)
	}

	return nil, menusMap
}

func (r *MenuSrv) appendChildren(menu *model.MenuTree, treeMap map[uint][]model.MenuTree) (err error) {
	menu.Children = treeMap[menu.ID]
	for i := 0; i < len(menu.Children); i++ {
		err = r.appendChildren(&menu.Children[i], treeMap)
	}

	return err
}

func (r *MenuSrv) Create(menu model.MenuFillAble) response.Resp {
	if err := global.Gorm.Model(&model.Menu{}).Create(&model.Menu{
		MenuFillAble: menu,
	}).Error; err != nil {
		return response.ErrCreate
	}

	return response.OK
}

func (r MenuSrv) FindByID(id uint) (error, model.Menu) {
	var menu model.Menu
	err := global.Gorm.Model(&model.Menu{}).Where("`id` = ?", id).First(&menu).Error

	return err, menu
}

func (r *MenuSrv) Show(id uint) response.Resp {
	_, menu := r.FindByID(id)
	if menu.ID == 0 {
		return response.ErrRecordNotFound
	}
	return response.OK.WithData(menu)
}

func (r MenuSrv) Update(id uint, req request.MenuUpdate) response.Resp {
	_, menu := r.FindByID(id)
	if menu.ID == 0 {
		return response.ErrRecordNotFound
	}
	updates := structs.Map(req)
	if err := global.Gorm.Model(&menu).Updates(updates).Error; err != nil {
		return response.ErrStore
	}
	return response.OK
}

func (r MenuSrv) Del(id uint) response.Resp {
	_, menu := r.FindByID(id)
	if menu.ID == 0 {
		return response.ErrRecordNotFound
	}
	// 删除关联关系
	err := global.Gorm.Unscoped().Select(clause.Associations).Delete(&menu).Error
	if err != nil {
		return response.ErrDel.SetMsg("菜单关联关系删除失败")
	}

	// 删除所有子菜单
	err = global.Gorm.Unscoped().Delete(&model.Menu{}, "id = ? or pid = ?", id, id).Error
	if err != nil {
		return response.ErrDel
	}

	return response.OK
}
